<template>
  <div class="tl-upload-list">
    <div :class="cssClass">
      {{ title }}
      <slot name="title"></slot>
      <div class="simple-pager">
        <span v-if="limitType"> 请上传{{ limitType }}文件&nbsp;&nbsp;</span>
        <span v-if="limitSize">单个附件不超过{{ limitSize }}kb&nbsp;&nbsp;</span>
        <span v-if="extendDesc">{{ extendDesc }}kb&nbsp;&nbsp;</span>
      </div>
      <div class="toolbar">
        <el-upload class="tl-upload" style="display: inline-block;" v-if="editable" :show-file-list="false" :action="baseUrl + uploadUrl" :headers="header" :file-list="uploadFileList" :data="postData" multiple :on-success="uploadSuccess" :before-upload="beforeUpload" :on-error="uploadFail" :on-progress="progress">
          <el-button type="text" size="medium" icon="el-icon-upload" :disabled="!editable" style="display:block">请添加文件</el-button>
          <div class="upload-queue">
            <el-tooltip class="item" :key="file.uid" v-for="file in uploadingFileList" effect="dark" :content="file.name" placement="top">
              <el-progress :text-inside="true" :stroke-width="20" :percentage="parseInt(file.percentage)" :format="formatProcess"></el-progress>
            </el-tooltip>
          </div>
        </el-upload>
        <slot name="toolbar"></slot>
      </div>
    </div>
    <div class="tl-upload">
      <el-table ref="mainTable" class="tl-table" :data="fileList" row-key="id" border fit :default-sort="{ prop: 'id', order: 'ascending' }">
        <el-table-column type="index" label="序号" width="55px" align="center"> </el-table-column>
        <el-table-column prop="displayname" min-width="200px" label="文件名称"></el-table-column>
        <el-table-column prop="filetype" label="文件类型" width="120px" align="center"></el-table-column>
        <el-table-column prop="filesize" label="文件大小" width="120px" align="center"></el-table-column>
        <el-table-column prop="createon" label="上传时间" width="180px" :formatter="dateFormat"></el-table-column>
        <el-table-column label="操作" width="210px" header-align="center" align="center" v-slot="slotProps" fixed="right">
          <el-button type="text" :disabled="slotProps.row.ex_type !== 'image' && slotProps.row.ex_type !== 'pdf'" icon="el-icon-view" @click="handleView(slotProps.row)">查看</el-button>
          <el-button type="text" icon="el-icon-download" @click="handleDownload(slotProps.row)">下载</el-button>
          <el-button type="text" icon="el-icon-delete" @click="handleRemove(slotProps.row)" :disabled="editable ? (createUserPermission ? slotProps.row.createuser !== $store.getters.user.id : !editable) : !editable">删除</el-button>
        </el-table-column>
      </el-table>
      <div :id="viewerId"></div>
      <el-dialog :visible.sync="pdfVisible" :title="pdfTitle" v-dialogDrag class="tl-dialog" width="90%" :append-to-body="true">
        <iframe v-show="pdfFile" :src="pdfFile" width="100%" height="600px"></iframe>
        <div slot="footer" class="dialog-footer" style="text-align:center;">
          <el-button type="primary" @click="pdfVisible = false">关闭</el-button>
        </div>
      </el-dialog>
    </div>
  </div>
</template>

<script>
import axios from '@tapui/utils/request'
import { getAction, deleteAction, putAction } from '@tapui/utils/http'
import Viewer from 'viewerjs'
import 'viewerjs/dist/viewer.min.css'
import { Loading } from 'element-ui'
export default {
  name: 'TlAttachment',
  components: {},
  data() {
    return {
      fileList: [],
      uploadFileList: [],
      fileCount: 0,
      waitCount: 0,
      previewTitle: '附件预览',
      previewVisible: false,
      postData: {
        sourceType: this.sourceType,
        sourceId: this.sourceId
      },
      baseUrl: axios.defaults.baseURL,
      header: {
        Authorization: 'Bearer ' + this.$store.getters.token
      },
      imageViewer: null,
      totalPage: 0,
      visible: false,
      pdfVisible: false,
      pdfTitle: 'pdf文件',
      pdfFile: null,
      url: {
        download: '/cbo/attachment/download',
        display: '/cbo/attachment/display',
        query: '/cbo/attachment/queryAttachmentList',
        queryCount: '/cbo/attachment/calculateCount'
      },
      viewerId: 'viewer',
      loading: null,
      imgFileTypes: ['png', 'jpg', 'jpeg', 'bmp']
    }
  },
  props: {
    sourceType: {
      type: String,
      required: true
    },
    sourceId: {
      type: Number,
      default: 0
    },
    limitCount: {
      type: Number,
      default: 999999
    },
    limitType: {
      type: String,
      default: ''
    },
    limitSize: {
      // 单位Kb
      type: Number,
      default: 0
    },
    extendData: {
      type: Object,
      default: function() {
        return {}
      }
    },
    editable: {
      type: Boolean,
      default: true
    },
    extendDesc: {
      type: String,
      default: ''
    },
    btnTitle: {
      type: String,
      default: '附件'
    },
    title: {
      type: String,
      default: '附件'
    },
    disabled: {
      type: Boolean,
      default: false
    },
    cssClass: {
      type: String,
      default: 'tl-form-line-title'
    },
    uploadUrl: {
      type: String,
      default: '/cbo/attachment/upload'
    },
    deleteUrl: {
      type: String,
      default: '/cbo/attachment/delete'
    },
    createUserPermission: {
      type: Boolean,
      default: false
    }
  },
  computed: {
    imageList() {
      return this.fileList.filter((file) => file.ex_type === 'image')
    },
    // 正在上传的文件列表，用于显示进度条
    uploadingFileList() {
      return this.uploadFileList.filter((file) => !file.success)
    }
  },
  methods: {
    open() {
      this.postData = {
        sourceType: this.sourceType,
        sourceId: this.sourceId
      }
      this.viewerId = 'viewer' + this.sourceType + this.sourceId + Math.floor(Math.random() * 100)
      this.postData = { ...this.postData, ...this.extendData }
      this.loadData()
    },
    previewOpen() {
      this.$nextTick((_) => {
        this.$refs.preview.open()
      })
    },
    previewClose() {
      this.$nextTick((_) => {
        this.$refs.preview.close()
      })
    },
    loadData() {
      let data = {
        qry_sourceType: this.sourceType,
        qry_sourceId: this.sourceId
      }
      this.fileList = []
      getAction(this.url.query, { ...data, ...this.extendData }).then((res) => {
        if (res.success) {
          res.result.forEach((file) => {
            this.bindFileDisplayUrl(file)
          })
          this.fileList = res.result
          this.$nextTick((_) => {
            this.$refs.mainTable.doLayout()
          })
        } else {
          this.$tap.alert(res.message, 'warning')
        }
      })
    },
    /** 格式化日期 YYYY-MM-dd HH:mm:ss */
    dateFormat(row, column, cellValue, index) {
      let dateValue = row[column.property]
      return this.$tap.date.parseTime(dateValue)
    },
    beforeUpload(file) {
      if (this.limitCount < this.fileList.length + 1 + this.waitCount) {
        this.$tap.alert(`最多只能上传${this.limitCount}个附件!`, 'warning')
        return false
      }
      if (this.limitType) {
        let fileType = this.getFileExt(file.name)
        let isRight = false
        for (let type of this.limitType.split(';')) {
          if (type.indexOf(fileType) > -1) {
            isRight = true
            break
          }
        }
        if (!isRight) {
          this.$tap.alert(`上传附件只能是 ${this.limitType}格式!`, 'warning')
          return false
        }
      }
      if (this.limitSize > 0) {
        if (file.size / 1024 > this.limitSize) {
          this.$tap.alert(`上传附件不能大于 ${this.limitSize}kb!`, 'warning')
          return false
        }
      }
      this.openLoading()
      this.waitCount++
      return true
    },
    /** zhanglongfei 2020.9.18增加上传文件进度条，配套有compute中的uploadingFileList，data中uploadFileList,上传组件的file-list和class=upload-queue的div */
    progress(event, file, fileList) {
      this.uploadFileList = fileList
    },
    formatProcess(percentage) {
      return `${percentage}%`
    },
    uploadSuccess(response, file) {
      this.closeLoading()
      this.waitCount--
      let existFile = this.uploadFileList.find((m) => m.uid === file.uid)
      if (existFile) {
        this.$set(existFile, 'success', true)
      }
      if (response.success) {
        this.$tap.message('上传成功')
        this.bindFileDisplayUrl(response.result)
        this.fileList.push(response.result)
        this.$emit('updateData')
      } else {
        this.$tap.alert(`上传失败：${response.message}`, 'warning')
      }
    },
    uploadFail() {
      this.closeLoading()
      this.waitCount--
    },
    bindFileDisplayUrl(file) {
      file.ex_type = 'other'
      file.ex_base64 = ''
      let fileType = this.getFileExt(file.displayname)
      if (fileType === 'jpg') {
        file.ex_type = 'image'
        // if (this.listType === 'thumb') this.display(file)
        this.display(file)
      } else if (fileType === 'pdf') {
        file.ex_type = 'pdf'
      } else if (this.imgFileTypes.includes(fileType)) {
        file.ex_type = 'image'
        this.display(file)
      }
    },
    display(file) {
      if (!file.id) return
      axios({
        url: this.url.download,
        method: 'post',
        data: { attachmentId: file.id },
        responseType: 'arraybuffer'
      }).then((response) => {
        file.ex_base64 = 'data:image/png;base64,' + this.$tap.util.bufferToBase64(response)
      })
    },
    getFileExt(fileName) {
      let arr = fileName.split('.')
      if (arr.length === 0) return ''
      else return arr[arr.length - 1].toString().toLowerCase()
    },
    handleView(file) {
      if (file.ex_type === 'image') {
        this.viewImage(file)
      } else if (file.ex_type === 'pdf') {
        this.viewPdf(file)
      }
    },
    viewImage(file) {
      // for (let item of this.imageList) {
      //   if (!item.ex_base64) this.asyncDisplay(item)
      // }
      if (!this.imageViewer) {
        this.imageViewer = new Viewer(document.getElementById(this.viewerId), {
          url(image) {
            return image.ex_base64
          },
          title: [
            1,
            (image, imageData) => {
              return `${this.imageList[this.imageViewer.index].displayname} (${imageData.naturalWidth} × ${imageData.naturalHeight})`
            }
          ]
        })
      }
      this.imageViewer.options.zIndex = 666666
      this.imageViewer.images = this.imageList
      this.imageViewer.length = this.imageViewer.images.length
      let idx = this.imageList.findIndex((item) => item.id === file.id)
      this.imageViewer.index = idx
      this.imageViewer.show()
    },
    viewPdf(file) {
      axios({
        url: this.url.download,
        method: 'post',
        data: { attachmentId: file.id },
        responseType: 'blob'
      }).then((response) => {
        let url = this.getObjectURL(response)
        this.pdfFile = `/static/plugins/pdfjs/web/viewer.html?file=${url}`
        this.pdfTitle = file.displayname
        this.pdfVisible = true
      })
    },
    getObjectURL(file) {
      let url = null
      if (window.createObjectURL !== undefined) {
        // basic
        url = window.createObjectURL(file)
      } else if (window.webkitURL !== undefined) {
        // webkit or chrome
        try {
          url = window.webkitURL.createObjectURL(file)
        } catch (error) {}
      } else if (window.URL !== undefined) {
        // mozilla(firefox)
        try {
          url = window.URL.createObjectURL(file)
        } catch (error) {}
      }
      return url
    },
    handleRemove(file, fileList) {
      this.$tap.confirm('确定移除文件').then(() => {
        this.doRemove(file)
      })
    },
    doRemove(file) {
      deleteAction(this.deleteUrl, { ids: file.id }).then((res) => {
        if (res.success) {
          this.$tap.message('删除成功')
          this.$emit('updateData')
          this.fileList.splice(this.fileList.findIndex((item) => item.id === file.id), 1)
        } else {
          this.$tap.alert(`删除失败：${res.message}`, 'warning')
        }
      })
    },
    handleDownload(file) {
      axios({
        url: this.url.download,
        method: 'post',
        data: { attachmentId: file.id },
        responseType: 'blob'
      }).then((response) => {
        this.doDownload(response, file)
      })
    },
    doDownload(response, file) {
      var blob = new Blob([response], { type: 'application/octet-stream;charset=utf-8' })
      var tempObjectUrl = window.URL.createObjectURL(blob)
      var aLink = document.createElement('a')
      aLink.style.display = 'none'
      aLink.download = file.displayname
      aLink.href = tempObjectUrl
      document.body.appendChild(aLink)
      aLink.click()
      document.body.removeChild(aLink)
      window.URL.revokeObjectURL(tempObjectUrl)
    },
    handleExceed(files, fileList) {
      this.$tap.alert(`最多可以上传${this.limitCount}个文件`, 'warning')
    },
    queryCount() {},
    /** 打开遮罩 */
    openLoading() {
      this.loading = Loading.service({
        lock: true,
        text: '加载中……',
        background: 'rgba(0, 0, 0, 0.7)'
      })
    },
    /** 关闭遮罩 */
    closeLoading() {
      this.loading.close()
    },
    close() {
      this.waitCount = 0
      this.uploadFileList = []
      this.$emit('close', this.fileList)
    }
  },
  watch: {
    fileList(newVal, oldVal) {
      this.$emit('loaded', newVal.length, this.sourceType)
    }
  }
}
</script>

<style lang="scss">
.exchange-tab .el-radio-button span.el-radio-button__inner {
  padding-right: 10px;
  padding-left: 10px;
}
</style>
<style scoped lang="scss">
.tl-upload {
  position: relative;
}
.upload-queue {
  clear: both;
  position: absolute;
  width: 80%;
  background: white;
  text-align: left;
  z-index: 2;
  left: 125px;
  top: 0;
  .el-progress {
    display: inline-block;
    margin: 6px 10px 0 0;
    width: 150px;
  }
}
</style>
